#include "protocol.h"

extern ringblkbuf_t rbb;
extern param_t param;
uint8_t data[DATA_SIZE];

void protocol_run(void)
{
    uint8_t ack_data[4] = {param.host_id, ACK, 0x53, 0xF7};
    uint8_t nck_data[4] = {param.host_id, NAK, 0x53, 0xF7};
    uint32_t app_address = APP_ADDRESS;
    fmc_erase(APP_ADDRESS,0x800,104);
    while (1)
    {
        if (rbb.current_count > 0)
        {
            ringblkbuf_read(&rbb, data, DATA_SIZE);
            uint16_t crc;
            switch (data[1])
            {
            case ENQ:
                crc = (uint16_t)(data[2] << 8) + data[3];
                if (crc == crc16(data, 2))
                {
                    usart0_dma_send(ack_data, 4);
                }
                break;
            case DAT:
                crc = (uint16_t)(data[11] << 8) + data[12];
                if (crc == crc16(data, 11))
                {
                    fmc_write(app_address, (uint32_t *)&data[3], 1);
                    app_address += 4;
                    fmc_write(app_address, (uint32_t *)&data[7], 1);
                    app_address += 4;
                    usart0_dma_send(ack_data, 4);
                }
                break;
            case VER:
                crc = (uint16_t)(data[4] << 8) + data[5];
                if (crc == crc16(data, 4))
                {
                    param.version_major = data[2];
                    param.version_minor = data[3];
                    usart0_dma_send(ack_data, 4);
                }
                break;
            case RUN:
                crc = (uint16_t)(data[2] << 8) + data[3];
                if (crc == crc16(data, 2))
                {
                    param.boot_flag = BOOT2APP_FLAG;
                    fmc_erase(PARAM_ADDR,0x800,1);
                    fmc_write(PARAM_ADDR,(uint32_t *)&param,sizeof(param_t)/4);
                    usart0_dma_send(ack_data, 4);
                    NVIC_SystemReset();
                }
                break;
            default:
                usart0_dma_send(nck_data, 4);
                break;
            }
        }
    }
}
